home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / cvs-1_3.lha / cvs-1.3 / lib / sighandle.c < prev    next >
C/C++ Source or Header  |  1992-03-31  |  9KB  |  409 lines

  1. /* sighandle.c -- Library routines for manipulating chains of signal handlers
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com>
  19.    Brian Berliner <berliner@Sun.COM> added POSIX support */
  20.  
  21. /*************************************************************************
  22.  *
  23.  * signal.c -- This file contains code that manipulates chains of signal
  24.  *             handlers.
  25.  *
  26.  *             Facilities are provided to register a signal handler for
  27.  *             any specific signal.  When a signal is received, all of the
  28.  *             registered signal handlers are invoked in the reverse order
  29.  *             in which they are registered.  Note that the signal handlers
  30.  *             must not themselves make calls to the signal handling
  31.  *             facilities.
  32.  *
  33.  * @(#)sighandle.c 1.9 92/03/31
  34.  *
  35.  *************************************************************************/
  36.  
  37. #include <sys/types.h>
  38. #include <stdio.h>
  39. #include <signal.h>
  40.  
  41. #ifdef STDC_HEADERS
  42. #include <stdlib.h>
  43. #else
  44. #if __STDC__
  45. char *calloc(unsigned nelem, unsigned size);
  46. char *malloc(unsigned size);
  47. #else
  48. char *calloc();
  49. char *malloc();
  50. #endif /* __STDC__ */
  51. #endif /* STDC_HEADERS */
  52.  
  53. #ifdef _MINIX
  54. #undef    POSIX        /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
  55. #endif
  56.  
  57. #ifndef SIGTYPE
  58. #define SIGTYPE void
  59. #endif
  60.  
  61. /* Define the highest signal number (usually) */
  62. #ifndef SIGMAX
  63. #define    SIGMAX    32
  64. #endif
  65.  
  66. /* Define linked list of signal handlers structure */
  67. struct SIG_hlist {
  68.     SIGTYPE            (*handler)();
  69.     struct SIG_hlist    *next;
  70. };
  71.  
  72. /*
  73.  * Define array of lists of signal handlers.  Note that this depends on
  74.  * the implementation to initialize each element to a null pointer.
  75.  */
  76.  
  77. static    struct SIG_hlist    **SIG_handlers;
  78.  
  79. /* Define array of default signal vectors */
  80.  
  81. #ifdef POSIX
  82. static    struct sigaction    *SIG_defaults;
  83. #else
  84. #ifdef BSD_SIGNALS
  85. static    struct sigvec        *SIG_defaults;
  86. #else
  87. static    SIGTYPE            (**SIG_defaults)();
  88. #endif
  89. #endif
  90.  
  91. /* Critical section housekeeping */
  92. static    int        SIG_crSectNest = 0;    /* Nesting level */
  93. #ifdef POSIX
  94. static    sigset_t    SIG_crSectMask;        /* Signal mask */
  95. #else
  96. static    int        SIG_crSectMask;        /* Signal mask */
  97. #endif
  98.  
  99. /*
  100.  * Initialize the signal handler arrays
  101.  */
  102.  
  103. static int SIG_init()
  104. {
  105.     int i;
  106. #ifdef POSIX
  107.     sigset_t sigset_test;
  108. #endif
  109.  
  110.     if (SIG_defaults && SIG_handlers)    /* already allocated */
  111.         return (0);
  112.  
  113. #ifdef POSIX
  114.     (void) sigfillset(&sigset_test);
  115.     for (i = 1; sigismember(&sigset_test, i) == 1; i++)
  116.         ;
  117.     if (i < SIGMAX)
  118.         i = SIGMAX;
  119.     i++;
  120.     if (!SIG_defaults)
  121.         SIG_defaults = (struct sigaction *)
  122.             calloc(i, sizeof(struct sigaction));
  123.     (void) sigemptyset(&SIG_crSectMask);
  124. #else
  125.     i = SIGMAX+1;
  126. #ifdef BSD_SIGNALS
  127.     if (!SIG_defaults)
  128.         SIG_defaults = (struct sigvec *)
  129.             calloc(i, sizeof(struct sigvec));
  130. #else
  131.     if (!SIG_defaults)
  132.         SIG_defaults = (SIGTYPE (**)())
  133.             calloc(i, sizeof(SIGTYPE (**)()));
  134. #endif
  135.     SIG_crSectMask = 0;
  136. #endif
  137.     if (!SIG_handlers)
  138.         SIG_handlers = (struct SIG_hlist **)
  139.             calloc(i, sizeof(struct SIG_hlist *));
  140.     return (!SIG_defaults || !SIG_handlers);
  141. }
  142.  
  143. /*
  144.  * The following invokes each signal handler in the reverse order in which
  145.  * they were registered.
  146.  */
  147.  
  148. static SIGTYPE SIG_handle(sig)
  149. int            sig;
  150. {
  151.     struct SIG_hlist    *this;
  152.  
  153.     /* Dispatch signal handlers */
  154.     this = SIG_handlers[sig];
  155.     while (this != (struct SIG_hlist *) NULL)
  156.     {
  157.         (*this->handler)(sig);
  158.         this = this->next;
  159.     }
  160.  
  161.     return;
  162. }
  163.  
  164. /*
  165.  * The following registers a signal handler.  If the handler is already
  166.  * registered, it is not registered twice, nor is the order in which signal
  167.  * handlers are invoked changed.  If this is the first signal handler
  168.  * registered for a given signal, the old sigvec structure is saved for
  169.  * restoration later.
  170.  */
  171.  
  172. int SIG_register(sig,fn)
  173. int    sig;
  174. SIGTYPE    (*fn)();
  175. {
  176.     int            val;
  177.     struct SIG_hlist    *this;
  178. #ifdef POSIX
  179.     struct sigaction    act;
  180.     sigset_t        sigset_mask, sigset_omask;
  181. #else
  182. #ifdef BSD_SIGNALS
  183.     struct sigvec        vec;
  184.     int            mask;
  185. #endif
  186. #endif
  187.  
  188.     /* Initialize */
  189.     if (SIG_init() != 0)
  190.         return (-1);
  191.     val = 0;
  192.  
  193.     /* Block this signal while we look at handler chain */
  194. #ifdef POSIX
  195.     (void) sigemptyset(&sigset_mask);
  196.     (void) sigaddset(&sigset_mask, sig);
  197.     (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
  198. #else
  199. #ifdef BSD_SIGNALS
  200.     mask = sigblock(sigmask(sig));
  201. #endif
  202. #endif
  203.  
  204.     /* See if this handler was already registered */
  205.     this = SIG_handlers[sig];
  206.     while (this != (struct SIG_hlist *) NULL)
  207.     {
  208.         if (this->handler == fn) break;
  209.         this = this->next;
  210.     }
  211.  
  212.     /* Register the new handler only if it is not already registered. */
  213.     if (this == (struct SIG_hlist *) NULL)
  214.     {
  215.  
  216.         /*
  217.          * If this is the first handler registered for this signal,
  218.          * set up the signal handler dispatcher
  219.          */
  220.  
  221.         if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
  222.         {
  223. #ifdef POSIX
  224.             act.sa_handler = SIG_handle;
  225.             (void) sigemptyset(&act.sa_mask);
  226.             act.sa_flags = 0;
  227.             val = sigaction(sig, &act, &SIG_defaults[sig]);
  228. #else
  229. #ifdef BSD_SIGNALS
  230.             bzero((char *)&vec, sizeof(vec));
  231.             vec.sv_handler = SIG_handle;
  232.             val = sigvec(sig, &vec, &SIG_defaults[sig]);
  233. #else
  234.             if ((SIG_defaults[sig] = signal(sig, SIG_handle)) ==
  235.                 (SIGTYPE (*)()) -1)
  236.                 val = -1;
  237. #endif
  238. #endif
  239.         }
  240.  
  241.         /* If not, register it */
  242.         if ((val == 0) && (this == (struct SIG_hlist *) NULL))
  243.         {
  244.             this = (struct SIG_hlist *)
  245.                                   malloc(sizeof(struct SIG_hlist));
  246.             if (this == NULL)
  247.             {
  248.                 val = -1;
  249.             }
  250.             else
  251.             {
  252.                 this->handler = fn;
  253.                 this->next = SIG_handlers[sig];
  254.                 SIG_handlers[sig] = this;
  255.             }
  256.         }
  257.     }
  258.  
  259.     /* Unblock the signal */
  260. #ifdef POSIX
  261.     (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
  262. #else
  263. #ifdef BSD_SIGNALS
  264.     (void) sigsetmask(mask);
  265. #endif
  266. #endif
  267.  
  268.     return val;
  269. }
  270.  
  271. /*
  272.  * The following deregisters a signal handler.  If the last signal handler for
  273.  * a given signal is deregistered, the default sigvec information is restored.
  274.  */
  275.  
  276. int SIG_deregister(sig,fn)
  277. int    sig;
  278. SIGTYPE    (*fn)();
  279. {
  280.     int            val;
  281.     struct SIG_hlist    *this;
  282.     struct SIG_hlist    *last;
  283. #ifdef POSIX
  284.     sigset_t        sigset_mask, sigset_omask;
  285. #else
  286. #ifdef BSD_SIGNALS
  287.     int            mask;
  288. #endif
  289. #endif
  290.  
  291.     /* Initialize */
  292.     if (SIG_init() != 0)
  293.         return (-1);
  294.     val = 0;
  295.     last = (struct SIG_hlist *) NULL;
  296.  
  297.     /* Block this signal while we look at handler chain */
  298. #ifdef POSIX
  299.     (void) sigemptyset(&sigset_mask);
  300.     (void) sigaddset(&sigset_mask, sig);
  301.     (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
  302. #else
  303. #ifdef BSD_SIGNALS
  304.     mask = sigblock(sigmask(sig));
  305. #endif
  306. #endif
  307.  
  308.     /* Search for the signal handler */
  309.     this = SIG_handlers[sig];
  310.     while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
  311.     {
  312.         last = this;
  313.         this = this->next;
  314.     }
  315.  
  316.     /* If it was registered, remove it */
  317.     if (this != (struct SIG_hlist *) NULL)
  318.     {
  319.         if (last == (struct SIG_hlist *) NULL)
  320.         {
  321.             SIG_handlers[sig] = this->next;
  322.         }
  323.         else
  324.         {
  325.             last->next = this->next;
  326.         }
  327.         free((char *) this);
  328.     }
  329.  
  330.     /* Restore default behavior if there are no registered handlers */
  331.     if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
  332.     {
  333. #ifdef POSIX
  334.         val = sigaction(sig, &SIG_defaults[sig],
  335.                 (struct sigaction *) NULL);
  336. #else
  337. #ifdef BSD_SIGNALS
  338.         val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
  339. #else
  340.         if (signal(sig, SIG_defaults[sig]) == (SIGTYPE (*)()) -1)
  341.             val = -1;
  342. #endif
  343. #endif
  344.     }
  345.  
  346.     /* Unblock the signal */
  347. #ifdef POSIX
  348.     (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
  349. #else
  350. #ifdef BSD_SIGNALS
  351.     (void) sigsetmask(mask);
  352. #endif
  353. #endif
  354.  
  355.     return val;
  356. }
  357.  
  358. /*
  359.  * The following begins a critical section.
  360.  */
  361.  
  362. void SIG_beginCrSect()
  363. {
  364.     if (SIG_init() == 0)
  365.     {
  366.         if (SIG_crSectNest == 0)
  367.         {
  368. #ifdef POSIX
  369.             sigset_t sigset_mask;
  370.  
  371.             (void) sigfillset(&sigset_mask);
  372.             (void) sigprocmask(SIG_SETMASK,
  373.                        &sigset_mask, &SIG_crSectMask);
  374. #else
  375. #ifdef BSD_SIGNALS
  376.             SIG_crSectMask = sigblock(~0);
  377. #else
  378.             /* TBD */
  379. #endif
  380. #endif
  381.         }
  382.         SIG_crSectNest++;
  383.     }
  384. }
  385.  
  386. /*
  387.  * The following ends a critical section.
  388.  */
  389.  
  390. void SIG_endCrSect()
  391. {
  392.     if (SIG_init() == 0)
  393.     {
  394.         SIG_crSectNest--;
  395.         if (SIG_crSectNest == 0)
  396.         {
  397. #ifdef POSIX
  398.             (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
  399. #else
  400. #ifdef BSD_SIGNALS
  401.             (void) sigsetmask(SIG_crSectMask);
  402. #else
  403.             /* TBD */
  404. #endif
  405. #endif
  406.         }
  407.     }
  408. }
  409.